
using Com.Ctrip.Framework.Apollo;
using Consul;
using Extentions;
using InventoryIssue.API.Read.Extensions;
using InventoryIssue.Infrastructrue.Implement;
using InventoryIssue.Infrastructrue.Interface;
using Microsoft.Extensions.Primitives;
using Microsoft.OpenApi.Models;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
using System.Reflection;

namespace InventoryIssue.API.Read
{
    /// <summary>
    /// 123
    /// </summary>
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.

            builder.Services.AddControllers();
            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddMediatR(cfg =>
            {
                cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly());
            });
            builder.Services.AddAutoMapper(typeof(MyAutoMapper));
            builder.Services.AddScoped<IDatabaseContext, DatabaseContext>();
            builder.Services.AddScoped<DatabaseContext>();
            builder.Services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));
            builder.Services.AddSwaggerGen(c =>
            {
                //jwt授权在swagger中的应用
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {
                    Description = "在下框中输入需要请求接口中的Jwt授权Token：Bearer Token",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });
                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        new string[] { }
                    }
                });
                c.IncludeXmlComments(AppContext.BaseDirectory + "/InventoryIssue.API.Read.xml", true);

                c.AddServer(new OpenApiServer()
                {
                    Url = "/lssueread",
                    Description = "Kong GateWay"
                }
                );
            });
            builder.Services.AddControllers(x => x.Filters.Add<GlobalExceptionFilter>());
            builder.Services.AddJWT(builder);
            builder.Services.AddSignalR();
            //builder.Services.AddEndpointsApiExplorer();
            //builder.Services.AddSwaggerGen();


            static void RegisterConsul()
            {
                try
                {
                    var consulClient = new ConsulClient(p => {
                        p.Address = new Uri("http://112.126.93.146:8500");
                    });
                    // 2. 确保健康检查端点可访问
                    var httpCheck = new AgentServiceCheck()
                    {
                        DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                        Interval = TimeSpan.FromSeconds(10),
                        HTTP = "http://112.126.93.146:8010/WeatherForecast", // 确认此端口服务是否运行
                        Timeout = TimeSpan.FromSeconds(5)
                    };
                    // 3. 添加标签方便识别
                    var registration = new AgentServiceRegistration()
                    {
                        Checks = new[] { httpCheck },
                        ID = $"lnventorylssuereadservice-{Guid.NewGuid()}", // 更易读的ID
                        Name = "lnventorylssuereadservice",                // 注意大小写一致性
                        Address = "112.126.93.146",                   // 纯IP正确
                        Port = 8010,                               // 端口与健康检查一致
                        Tags = new[] { "dotnet-service" }           // 添加标签
                    };

                    // 4. 添加错误处理
                    var result = consulClient.Agent.ServiceRegister(registration).Result;
                    Console.WriteLine($"服务注册成功! Status: {result.StatusCode}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Consul注册失败: {ex.Message}");
                }
            }

            var configuration = builder.Configuration;
            // 配置Serilog
            var elaUri = configuration["ELK:ElaticSearchUrl"];
            var userName = configuration["ELK:UserName"];
            var password = configuration["ELK:Password"];
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .Enrich.WithMachineName()
                .Enrich.WithThreadId()
                .Enrich.WithProcessId()
                .WriteTo.Console(new Serilog.Formatting.Compact.CompactJsonFormatter())
                .WriteTo.File("logs/lnventorylssueread-.txt",
                    rollingInterval: RollingInterval.Day,
                    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
                .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elaUri))
                {
                    IndexFormat = "lnventorylssueread-logs-{0:yyyy.MM.dd}",
                    AutoRegisterTemplate = true,
                    AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
                    ModifyConnectionSettings = conn => conn.BasicAuthentication(userName, password),
                    BufferBaseFilename = "./logs/serilog-buffer",
                    Period = TimeSpan.FromSeconds(2)
                })
                .CreateLogger();

            builder.Host.UseSerilog();

            builder.Configuration
                .AddApollo(builder.Configuration.GetSection("Apollo"))
                .AddDefault()
                .AddNamespace("application");


            var app = builder.Build();
            app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

            if (app.Configuration is IConfigurationRoot configRoot)
                ChangeToken.OnChange(
                () => configRoot.GetReloadToken(),
                () => Console.WriteLine($"配置已更新: {app.Configuration.GetValue<string>("wmss")}"));

            app.UseSwagger();
            app.UseSwaggerUI();

            // 配置中间件之前初始化数据库
            using (var scope = app.Services.CreateScope())
            {
                try
                {
                    var dbContext = scope.ServiceProvider.GetRequiredService<IDatabaseContext>();
                    dbContext.InitializeDatabase();
                }
                catch (Exception ex)
                {
                    var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "数据库初始化失败");
                }
            }

            app.UseAuthorization();

            app.UseStaticFiles(); 

            app.MapHub<ChatHub>("/hubs/stock");

            app.MapControllers();

            RegisterConsul();

            app.Run();
        }
    }
}
